package com.ww.juc.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BoundedBuffer {

    final Lock lock = new ReentrantLock();

    final Condition notFull = lock.newCondition();

    final Condition notEmpty = lock.newCondition();

    final Object[] items = new Object[100];
    int putptr = 0, takeptr = 0, count = 0;

    /**
     * 生产者
     * @param x
     * @throws InterruptedException
     */
    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                notFull.await();
            }
            items[putptr] = x;
            System.out.println("位置" + putptr + "，生产了" + x);
            if (++putptr == items.length) {
                putptr = 0;
            }
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 消费者
     * @return
     * @throws InterruptedException
     */
    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (0 == count) {
                notEmpty.await();
            }
            Object x = items[takeptr];
            System.out.println("位置" + takeptr + "，消费了" + x);
            if (++takeptr == items.length) {
                takeptr = 0;
            }
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 位置0，生产了100
     * 位置0，消费了100
     * 位置1，生产了101
     * 位置1，消费了101
     * 位置2，生产了102
     * 位置2，消费了102
     * 位置3，生产了103
     * 位置3，消费了103
     * 位置4，生产了104
     * 位置4，消费了104
     * 位置5，生产了105
     * 位置5，消费了105
     * 位置6，生产了106
     * 位置6，消费了106
     * 位置7，生产了107
     * 位置7，消费了107
     * 位置8，生产了108
     * 位置8，消费了108
     * 位置9，生产了109
     * 位置9，消费了109
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        BoundedBuffer boundedBuffer = new BoundedBuffer();
        Integer i = 100;
        while (i < 200) {
            boundedBuffer.put(i);
            boundedBuffer.take();
            i++;
        }
    }
}
